package hn.cch.advanced.concurrent;

import org.junit.jupiter.api.Test;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class CountDownLatchDemo {

    public void code() {
        System.out.println(Thread.currentThread().getName() + ":begin");
        try {
            Thread.sleep((long) (Math.random() * 10000));
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(Thread.currentThread().getName() + ":end");
    }

    @Test
    public void testCount1() {
        int n = 3;
        ExecutorService threadPool = Executors.newFixedThreadPool(n);

        CountDownLatch countDownLatch1 = new CountDownLatch(1);
        for (int i = 0; i < n; i++) {
            threadPool.execute(() -> {
                System.out.println(Thread.currentThread().getName() + ":ready");
                try {
                    countDownLatch1.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(Thread.currentThread().getName() + ":start");
                code();// 业务代码
                System.out.println(Thread.currentThread().getName() + ":stop");

            });
        }
        System.out.println(Thread.currentThread().getName() + ":start");
        // 多个线程同时执行
        countDownLatch1.countDown();
        threadPool.shutdown();
        // 测试用例中创建的多线程都是守护线程
        ExecutorServiceUtil.complete(threadPool);
        System.out.println(Thread.currentThread().getName() + ":stop");

    }

    @Test
    public void testCountN() {
        int n = 3;
        ExecutorService threadPool = Executors.newFixedThreadPool(n);

        CountDownLatch countDownLatch = new CountDownLatch(n);
        for (int i = 0; i < n; i++) {
            threadPool.execute(() -> {
                System.out.println(Thread.currentThread().getName() + ":start");
                code();// 业务代码
                countDownLatch.countDown();
                System.out.println(Thread.currentThread().getName() + ":stop");
            });
        }
        System.out.println(Thread.currentThread().getName() + ":start");
        // 要等待N个线程执行才运行
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(Thread.currentThread().getName() + ":stop");
        threadPool.shutdown();
    }

    @Test
    public void testCountDownLatch() {
        int n = 3;
        ExecutorService threadPool = Executors.newFixedThreadPool(n);

        CountDownLatch countDownLatch1 = new CountDownLatch(1);
        CountDownLatch countDownLatchN = new CountDownLatch(n);
        for (int i = 0; i < n; i++) {
            threadPool.execute(() -> {
                System.out.println(Thread.currentThread().getName() + ":ready");
                try {
                    countDownLatch1.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(Thread.currentThread().getName() + ":start");
                code();// 业务代码
                countDownLatchN.countDown();
                System.out.println(Thread.currentThread().getName() + ":stop");

            });
        }
        System.out.println(Thread.currentThread().getName() + ":ready");
        // 多个线程同时执行
        countDownLatch1.countDown();
        System.out.println(Thread.currentThread().getName() + ":start");
        try {
            countDownLatchN.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(Thread.currentThread().getName() + ":stop");
        threadPool.shutdown();
    }
}
